/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* Generated By:JavaCC: Do not edit this line. QueryParser.java */

using System;
using Lucene.Net.Analysis;
using Lucene.Net.Documents;
using Term = Lucene.Net.Index.Term;
using Lucene.Net.Search;
using Searchable = Lucene.Net.Search.Searchable;
using Parameter = Lucene.Net.Util.Parameter;

namespace Lucene.Net.QueryParsers
{
	
	/// <summary> This class is generated by JavaCC.  The most important method is
	/// {@link #Parse(String)}.
	/// 
	/// The syntax for query strings is as follows:
	/// A Query is a series of clauses.
	/// A clause may be prefixed by:
	/// <ul>
	/// <li> a plus (<code>+</code>) or a minus (<code>-</code>) sign, indicating
	/// that the clause is required or prohibited respectively; or
	/// <li> a term followed by a colon, indicating the field to be searched.
	/// This enables one to construct queries which search multiple fields.
	/// </ul>
	/// 
	/// A clause may be either:
	/// <ul>
	/// <li> a term, indicating all the documents that contain this term; or
	/// <li> a nested query, enclosed in parentheses.  Note that this may be used
	/// with a <code>+</code>/<code>-</code> prefix to require any of a set of
	/// terms.
	/// </ul>
	/// 
	/// Thus, in BNF, the query grammar is:
	/// <pre>
	/// Query  ::= ( Clause )*
	/// Clause ::= ["+", "-"] [&lt;TERM&gt; ":"] ( &lt;TERM&gt; | "(" Query ")" )
	/// </pre>
	/// 
	/// <p>
	/// Examples of appropriately formatted queries can be found in the <a
	/// href="http://lucene.apache.org/java/docs/queryparsersyntax.html">query syntax
	/// documentation</a>.
	/// </p>
    /// 
    /// <p>In {@link RangeQuery}s, QueryParser tries to detect date values, e.g. <tt>date:[6/1/2005 TO 6/4/2005]</tt>
    /// produces a range query that searches for "date" fields between 2005-06-01 and 2005-06-04. Note
    /// that the format of the accpeted input depends on {@link #SetLocale(Locale) the locale}. This
    /// feature also assumes that your index uses the {@link DateField} class to store dates.
    /// If you use a different format (e.g. {@link DateTools}) and you still want QueryParser
    /// to turn local dates in range queries into valid queries you need to create your own
    /// query parser that inherits QueryParser and overwrites
    /// {@link #GetRangeQuery(String, String, String, boolean)}.</p>
    /// 
    /// <p>Note that QueryParser is <em>not</em> thread-safe.</p>
	/// 
	/// </summary>
	/// <author>  Brian Goetz
	/// </author>
	/// <author>  Peter Halacsy
	/// </author>
	/// <author>  Tatu Saloranta
	/// </author>
	
	public class QueryParser : QueryParserConstants
	{
		private void  InitBlock()
		{
			fuzzyMinSim = FuzzyQuery.defaultMinSimilarity;
			fuzzyPrefixLength = FuzzyQuery.defaultPrefixLength;
			jj_2_rtns = new JJCalls[1];
			jj_ls = new LookaheadSuccess();
		}
		
		private const int CONJ_NONE = 0;
		private const int CONJ_AND = 1;
		private const int CONJ_OR = 2;
		
		private const int MOD_NONE = 0;
		private const int MOD_NOT = 10;
		private const int MOD_REQ = 11;
		
		// make it possible to call setDefaultOperator() without accessing 
		// the nested class:
		/// <summary>Alternative form of QueryParser.Operator.AND </summary>
		public static readonly Operator AND_OPERATOR = Operator.AND;
		/// <summary>Alternative form of QueryParser.Operator.OR </summary>
		public static readonly Operator OR_OPERATOR = Operator.OR;
		
		/// <summary>The actual operator that parser uses to combine query terms </summary>
		private Operator operator_Renamed = OR_OPERATOR;
		
		internal bool lowercaseExpandedTerms = true;
		
		internal Analyzer analyzer;
		internal System.String field;
		internal int phraseSlop = 0;
		internal float fuzzyMinSim;
		internal int fuzzyPrefixLength;
		internal System.Globalization.CultureInfo locale = System.Threading.Thread.CurrentThread.CurrentCulture;
		
		/// <summary>The default operator for parsing queries. 
		/// Use {@link QueryParser#setDefaultOperator} to change it.
		/// </summary>
		[Serializable]
		public sealed class Operator : Parameter
		{
			internal Operator(System.String name) : base(name)
			{
			}
			public static readonly Operator OR = new Operator("OR");
			public static readonly Operator AND = new Operator("AND");
		}
		
		
		/// <summary>Constructs a query parser.</summary>
		/// <param name="f"> the default field for query terms.
		/// </param>
		/// <param name="a">  used to find terms in the query text.
		/// </param>
		public QueryParser(System.String f, Analyzer a) : this(new FastCharStream(new System.IO.StringReader("")))
		{
			analyzer = a;
			field = f;
		}
		
		/// <summary>Parses a query string, returning a {@link Lucene.Net.search.Query}.</summary>
		/// <param name="query"> the query string to be parsed.
		/// </param>
		/// <throws>  ParseException if the parsing fails </throws>
		public virtual Query Parse(System.String query)
		{
			ReInit(new FastCharStream(new System.IO.StringReader(query)));
			try
			{
				return Query(field);
			}
			catch (TokenMgrError tme)
			{
				throw new ParseException(tme.Message);
			}
			catch (BooleanQuery.TooManyClauses)
			{
				throw new ParseException("Too many boolean clauses");
			}
		}
		
		/// <returns> Returns the analyzer.
		/// </returns>
		public virtual Analyzer GetAnalyzer()
		{
			return analyzer;
		}
		
		/// <returns> Returns the field.
		/// </returns>
		public virtual System.String GetField()
		{
			return field;
		}
		
		/// <summary> Get the minimal similarity for fuzzy queries.</summary>
		public virtual float GetFuzzyMinSim()
		{
			return fuzzyMinSim;
		}
		
		/// <summary> Set the minimum similarity for fuzzy queries.
		/// Default is 0.5f.
		/// </summary>
		public virtual void  SetFuzzyMinSim(float fuzzyMinSim)
		{
			this.fuzzyMinSim = fuzzyMinSim;
		}
		
		/// <summary> Get the prefix length for fuzzy queries. </summary>
		/// <returns> Returns the fuzzyPrefixLength.
		/// </returns>
		public virtual int GetFuzzyPrefixLength()
		{
			return fuzzyPrefixLength;
		}
		
		/// <summary> Set the prefix length for fuzzy queries. Default is 0.</summary>
		/// <param name="fuzzyPrefixLength">The fuzzyPrefixLength to set.
		/// </param>
		public virtual void  SetFuzzyPrefixLength(int fuzzyPrefixLength)
		{
			this.fuzzyPrefixLength = fuzzyPrefixLength;
		}
		
		/// <summary> Sets the default slop for phrases.  If zero, then exact phrase matches
		/// are required.  Default value is zero.
		/// </summary>
		public virtual void  SetPhraseSlop(int phraseSlop)
		{
			this.phraseSlop = phraseSlop;
		}
		
		/// <summary> Gets the default slop for phrases.</summary>
		public virtual int GetPhraseSlop()
		{
			return phraseSlop;
		}
		
		
		/// <summary> Sets the boolean operator of the QueryParser.
		/// In default mode (<code>OR_OPERATOR</code>) terms without any modifiers
		/// are considered optional: for example <code>capital of Hungary</code> is equal to
		/// <code>capital OR of OR Hungary</code>.<br/>
		/// In <code>AND_OPERATOR</code> mode terms are considered to be in conjuction: the
		/// above mentioned query is parsed as <code>capital AND of AND Hungary</code>
		/// </summary>
		public virtual void  SetDefaultOperator(Operator op)
		{
			this.operator_Renamed = op;
		}
		
		
		/// <summary> Gets implicit operator setting, which will be either AND_OPERATOR
		/// or OR_OPERATOR.
		/// </summary>
		public virtual Operator GetDefaultOperator()
		{
			return operator_Renamed;
		}
		
		
		/// <summary> Whether terms of wildcard, prefix, fuzzy and range queries are to be automatically
		/// lower-cased or not.  Default is <code>true</code>.
		/// </summary>
		public virtual void  SetLowercaseExpandedTerms(bool lowercaseExpandedTerms)
		{
			this.lowercaseExpandedTerms = lowercaseExpandedTerms;
		}
		
		
		/// <seealso cref="SetLowercaseExpandedTerms(boolean)">
		/// </seealso>
		public virtual bool GetLowercaseExpandedTerms()
		{
			return lowercaseExpandedTerms;
		}
		
		/// <summary> Set locale used by date range parsing.</summary>
		public virtual void  SetLocale(System.Globalization.CultureInfo locale)
		{
			this.locale = locale;
		}
		
		/// <summary> Returns current locale, allowing access by subclasses.</summary>
		public virtual System.Globalization.CultureInfo GetLocale()
		{
			return locale;
		}
		
		protected internal virtual void  AddClause(System.Collections.ArrayList clauses, int conj, int mods, Query q)
		{
			bool required, prohibited;
			
			// If this term is introduced by AND, make the preceding term required,
			// unless it's already prohibited
			if (clauses.Count > 0 && conj == CONJ_AND)
			{
				BooleanClause c = (BooleanClause) clauses[clauses.Count - 1];
				if (!c.IsProhibited())
					c.SetOccur(BooleanClause.Occur.MUST);
			}
			
			if (clauses.Count > 0 && operator_Renamed == AND_OPERATOR && conj == CONJ_OR)
			{
				// If this term is introduced by OR, make the preceding term optional,
				// unless it's prohibited (that means we leave -a OR b but +a OR b-->a OR b)
				// notice if the input is a OR b, first term is parsed as required; without
				// this modification a OR b would parsed as +a OR b
				BooleanClause c = (BooleanClause) clauses[clauses.Count - 1];
				if (!c.IsProhibited())
					c.SetOccur(BooleanClause.Occur.SHOULD);
			}
			
			// We might have been passed a null query; the term might have been
			// filtered away by the analyzer.
			if (q == null)
				return ;
			
			if (operator_Renamed == OR_OPERATOR)
			{
				// We set REQUIRED if we're introduced by AND or +; PROHIBITED if
				// introduced by NOT or -; make sure not to set both.
				prohibited = (mods == MOD_NOT);
				required = (mods == MOD_REQ);
				if (conj == CONJ_AND && !prohibited)
				{
					required = true;
				}
			}
			else
			{
				// We set PROHIBITED if we're introduced by NOT or -; We set REQUIRED
				// if not PROHIBITED and not introduced by OR
				prohibited = (mods == MOD_NOT);
				required = (!prohibited && conj != CONJ_OR);
			}
			if (required && !prohibited)
				clauses.Add(new BooleanClause(q, BooleanClause.Occur.MUST));
			else if (!required && !prohibited)
				clauses.Add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
			else if (!required && prohibited)
				clauses.Add(new BooleanClause(q, BooleanClause.Occur.MUST_NOT));
			else
				throw new System.SystemException("Clause cannot be both required and prohibited");
		}
		
		
        /// <exception cref="ParseException">throw in overridden method to disallow
		/// </exception>
		protected internal virtual Query GetFieldQuery(System.String field, System.String queryText)
		{
			// Use the analyzer to get all the tokens, and then build a TermQuery,
			// PhraseQuery, or nothing based on the term count
			
			TokenStream source = analyzer.TokenStream(field, new System.IO.StringReader(queryText));
			System.Collections.ArrayList v = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
			Lucene.Net.Analysis.Token t;
			int positionCount = 0;
			bool severalTokensAtSamePosition = false;
			
			while (true)
			{
				try
				{
					t = source.Next();
				}
				catch (System.IO.IOException e)
				{
					t = null;
				}
				if (t == null)
					break;
				v.Add(t);
				if (t.GetPositionIncrement() != 0)
					positionCount += t.GetPositionIncrement();
				else
					severalTokensAtSamePosition = true;
			}
			try
			{
				source.Close();
			}
			catch (System.IO.IOException e)
			{
				// ignore
			}
			
			if (v.Count == 0)
				return null;
			else if (v.Count == 1)
			{
				t = (Lucene.Net.Analysis.Token) v[0];
				return new TermQuery(new Term(field, t.TermText()));
			}
			else
			{
				if (severalTokensAtSamePosition)
				{
					if (positionCount == 1)
					{
						// no phrase query:
						BooleanQuery q = new BooleanQuery(true);
						for (int i = 0; i < v.Count; i++)
						{
							t = (Lucene.Net.Analysis.Token) v[i];
							TermQuery currentQuery = new TermQuery(new Term(field, t.TermText()));
							q.Add(currentQuery, BooleanClause.Occur.SHOULD);
						}
						return q;
					}
					else
					{
						// phrase query:
						MultiPhraseQuery mpq = new MultiPhraseQuery();
                        mpq.SetSlop(phraseSlop);
                        System.Collections.ArrayList multiTerms = new System.Collections.ArrayList();
						for (int i = 0; i < v.Count; i++)
						{
							t = (Lucene.Net.Analysis.Token) v[i];
							if (t.GetPositionIncrement() == 1 && multiTerms.Count > 0)
							{
								mpq.Add((Term[]) multiTerms.ToArray(typeof(Term)));
								multiTerms.Clear();
							}
							multiTerms.Add(new Term(field, t.TermText()));
						}
						mpq.Add((Term[]) multiTerms.ToArray(typeof(Term)));
						return mpq;
					}
				}
				else
				{
					PhraseQuery q = new PhraseQuery();
					q.SetSlop(phraseSlop);
					for (int i = 0; i < v.Count; i++)
					{
						q.Add(new Term(field, ((Lucene.Net.Analysis.Token) v[i]).TermText()));
					}
					return q;
				}
			}
		}

		
		/// <summary> Base implementation delegates to {@link #GetFieldQuery(String,String)}.
		/// This method may be overridden, for example, to return
		/// a SpanNearQuery instead of a PhraseQuery.
		/// 
		/// </summary>
		/// <exception cref="ParseException">throw in overridden method to disallow
		/// </exception>
		protected internal virtual Query GetFieldQuery(System.String field, System.String queryText, int slop)
		{
			Query query = GetFieldQuery(field, queryText);
			
			if (query is PhraseQuery)
			{
				((PhraseQuery) query).SetSlop(slop);
			}
			if (query is MultiPhraseQuery)
			{
				((MultiPhraseQuery) query).SetSlop(slop);
			}
			
			return query;
		}
		
		
		/// <exception cref="ParseException">throw in overridden method to disallow
		/// </exception>
		protected internal virtual Query GetRangeQuery(System.String field, System.String part1, System.String part2, bool inclusive)
		{
			if (lowercaseExpandedTerms)
			{
				part1 = part1.ToLower();
				part2 = part2.ToLower();
			}
			try
			{
                System.DateTime d1;
                System.DateTime d2;

                try
                {
                    d1 = System.DateTime.Parse(part1, locale);
                }
                catch (System.Exception)
                {
                    d1 = System.DateTime.Parse(part1);
                }
                try
                {
                    d2 = System.DateTime.Parse(part2, locale);
                }
                catch (System.Exception)
                {
                    d2 = System.DateTime.Parse(part2);
                }

                if (inclusive)
                {
                    // The user can only specify the date, not the time, so make sure
                    // the time is set to the latest possible time of that date to really
                    // include all documents:
                    System.Globalization.Calendar cal = new System.Globalization.GregorianCalendar();
                    System.DateTime tempDate = d2;
                    d2 = d2.AddHours(23 - tempDate.Hour);
                    d2 = d2.AddMinutes(59 - tempDate.Minute);
                    d2 = d2.AddSeconds(59 - tempDate.Second);
                    d2 = d2.AddMilliseconds(999 - tempDate.Millisecond);
                }
                part1 = DateField.DateToString(d1);
                part2 = DateField.DateToString(d2);
            }
			catch (System.Exception)
			{
			}
			
			return new RangeQuery(new Term(field, part1), new Term(field, part2), inclusive);
		}
		
		/// <summary> Factory method for generating query, given a set of clauses.
		/// By default creates a boolean query composed of clauses passed in.
		/// 
		/// Can be overridden by extending classes, to modify query being
		/// returned.
		/// 
		/// </summary>
		/// <param name="clauses">Vector that contains {@link BooleanClause} instances
		/// to join.
		/// 
		/// </param>
		/// <returns> Resulting {@link Query} object.
		/// </returns>
		/// <exception cref="ParseException">throw in overridden method to disallow
		/// </exception>
		protected internal virtual Query GetBooleanQuery(System.Collections.ArrayList clauses)
		{
			return GetBooleanQuery(clauses, false);
		}
		
		/// <summary> Factory method for generating query, given a set of clauses.
		/// By default creates a boolean query composed of clauses passed in.
		/// 
		/// Can be overridden by extending classes, to modify query being
		/// returned.
		/// 
		/// </summary>
		/// <param name="clauses">Vector that contains {@link BooleanClause} instances
		/// to join.
		/// </param>
		/// <param name="disableCoord">true if coord scoring should be disabled.
		/// 
		/// </param>
		/// <returns> Resulting {@link Query} object.
		/// </returns>
		/// <exception cref="ParseException">throw in overridden method to disallow
		/// </exception>
		protected internal virtual Query GetBooleanQuery(System.Collections.ArrayList clauses, bool disableCoord)
		{
			BooleanQuery query = new BooleanQuery(disableCoord);
			for (int i = 0; i < clauses.Count; i++)
			{
				query.Add((BooleanClause) clauses[i]);
			}
			return query;
		}
		
		/// <summary> Factory method for generating a query. Called when parser
		/// parses an input term token that contains one or more wildcard
		/// characters (? and *), but is not a prefix term token (one
		/// that has just a single * character at the end)
		/// <p>
		/// Depending on settings, prefix term may be lower-cased
		/// automatically. It will not go through the default Analyzer,
		/// however, since normal Analyzers are unlikely to work properly
		/// with wildcard templates.
		/// <p>
		/// Can be overridden by extending classes, to provide custom handling for
		/// wildcard queries, which may be necessary due to missing analyzer calls.
		/// 
		/// </summary>
		/// <param name="field">Name of the field query will use.
		/// </param>
		/// <param name="termStr">Term token that contains one or more wild card
		/// characters (? or *), but is not simple prefix term
		/// 
		/// </param>
		/// <returns> Resulting {@link Query} built for the term
		/// </returns>
		/// <exception cref="ParseException">throw in overridden method to disallow
		/// </exception>
		protected internal virtual Query GetWildcardQuery(System.String field, System.String termStr)
		{
			if (lowercaseExpandedTerms)
			{
				termStr = termStr.ToLower();
			}
			Term t = new Term(field, termStr);
			return new WildcardQuery(t);
		}
		
		/// <summary> Factory method for generating a query (similar to
		/// {@link #getWildcardQuery}). Called when parser parses an input term
		/// token that uses prefix notation; that is, contains a single '*' wildcard
		/// character as its last character. Since this is a special case
		/// of generic wildcard term, and such a query can be optimized easily,
		/// this usually results in a different query object.
		/// <p>
		/// Depending on settings, a prefix term may be lower-cased
		/// automatically. It will not go through the default Analyzer,
		/// however, since normal Analyzers are unlikely to work properly
		/// with wildcard templates.
		/// <p>
		/// Can be overridden by extending classes, to provide custom handling for
		/// wild card queries, which may be necessary due to missing analyzer calls.
		/// 
		/// </summary>
		/// <param name="field">Name of the field query will use.
		/// </param>
		/// <param name="termStr">Term token to use for building term for the query
		/// (<b>without</b> trailing '*' character!)
		/// 
		/// </param>
		/// <returns> Resulting {@link Query} built for the term
		/// </returns>
		/// <exception cref="ParseException">throw in overridden method to disallow
		/// </exception>
		protected internal virtual Query GetPrefixQuery(System.String field, System.String termStr)
		{
			if (lowercaseExpandedTerms)
			{
				termStr = termStr.ToLower();
			}
			Term t = new Term(field, termStr);
			return new PrefixQuery(t);
		}
		
		
		/// <summary> Factory method for generating a query (similar to
		/// {@link #getWildcardQuery}). Called when parser parses
		/// an input term token that has the fuzzy suffix (~) appended.
		/// 
		/// </summary>
		/// <param name="field">Name of the field query will use.
		/// </param>
		/// <param name="termStr">Term token to use for building term for the query
		/// 
		/// </param>
		/// <returns> Resulting {@link Query} built for the term
		/// </returns>
		/// <exception cref="ParseException">throw in overridden method to disallow
		/// </exception>
		protected internal virtual Query GetFuzzyQuery(System.String field, System.String termStr, float minSimilarity)
		{
			if (lowercaseExpandedTerms)
			{
				termStr = termStr.ToLower();
			}
			Term t = new Term(field, termStr);
			return new FuzzyQuery(t, minSimilarity, fuzzyPrefixLength);
		}
		
		/// <summary> Returns a String where the escape char has been
		/// removed, or kept only once if there was a double escape.
		/// </summary>
		private System.String DiscardEscapeChar(System.String input)
		{
			char[] caSource = input.ToCharArray();
			char[] caDest = new char[caSource.Length];
			int j = 0;
			for (int i = 0; i < caSource.Length; i++)
			{
				if ((caSource[i] != '\\') || (i > 0 && caSource[i - 1] == '\\'))
				{
					caDest[j++] = caSource[i];
				}
			}
			return new System.String(caDest, 0, j);
		}
		
		/// <summary> Returns a String where those characters that QueryParser
		/// expects to be escaped are escaped by a preceding <code>\</code>.
		/// </summary>
		public static System.String Escape(System.String s)
		{
			System.Text.StringBuilder sb = new System.Text.StringBuilder();
			for (int i = 0; i < s.Length; i++)
			{
				char c = s[i];
				// NOTE: keep this in sync with _ESCAPED_CHAR below!
				if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':' || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~' || c == '*' || c == '?')
				{
					sb.Append('\\');
				}
				sb.Append(c);
			}
			return sb.ToString();
		}
		
		/// <summary> Command line tool to test QueryParser, using {@link Lucene.Net.analysis.SimpleAnalyzer}.
		/// Usage:<br>
		/// <code>java Lucene.Net.queryParser.QueryParser &lt;input&gt;</code>
		/// </summary>
		[STAThread]
		public static void  Main(System.String[] args)
		{
			if (args.Length == 0)
			{
				System.Console.Out.WriteLine("Usage: java Lucene.Net.queryParser.QueryParser <input>");
				System.Environment.Exit(0);
			}
			QueryParser qp = new QueryParser("field", new Lucene.Net.Analysis.SimpleAnalyzer());
			Query q = qp.Parse(args[0]);
			System.Console.Out.WriteLine(q.ToString("field"));
		}
		
		// *   Query  ::= ( Clause )*
		// *   Clause ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")" )
		public int Conjunction()
		{
			int ret = CONJ_NONE;
			switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
			{
				
				case Lucene.Net.QueryParsers.QueryParserConstants.AND: 
				case Lucene.Net.QueryParsers.QueryParserConstants.OR: 
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.AND: 
							Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.AND);
							ret = CONJ_AND;
							break;
						
						case Lucene.Net.QueryParsers.QueryParserConstants.OR: 
							Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.OR);
							ret = CONJ_OR;
							break;
						
						default: 
							jj_la1[0] = jj_gen;
							Jj_consume_token(- 1);
							throw new ParseException();
						
					}
					break;
				
				default: 
					jj_la1[1] = jj_gen;
					;
					break;
				
			}
			{
				if (true)
					return ret;
			}
			throw new System.ApplicationException("Missing return statement in function");
		}
		
		public int Modifiers()
		{
			int ret = MOD_NONE;
			switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
			{
				
				case Lucene.Net.QueryParsers.QueryParserConstants.NOT: 
				case Lucene.Net.QueryParsers.QueryParserConstants.PLUS: 
				case Lucene.Net.QueryParsers.QueryParserConstants.MINUS: 
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.PLUS: 
							Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.PLUS);
							ret = MOD_REQ;
							break;
						
						case Lucene.Net.QueryParsers.QueryParserConstants.MINUS: 
							Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.MINUS);
							ret = MOD_NOT;
							break;
						
						case Lucene.Net.QueryParsers.QueryParserConstants.NOT: 
							Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.NOT);
							ret = MOD_NOT;
							break;
						
						default: 
							jj_la1[2] = jj_gen;
							Jj_consume_token(- 1);
							throw new ParseException();
						
					}
					break;
				
				default: 
					jj_la1[3] = jj_gen;
					;
					break;
				
			}
			{
				if (true)
					return ret;
			}
			throw new System.ApplicationException("Missing return statement in function");
		}
		
		public Query Query(System.String field)
		{
			System.Collections.ArrayList clauses = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
			Query q, firstQuery = null;
			int conj, mods;
			mods = Modifiers();
			q = Clause(field);
			AddClause(clauses, CONJ_NONE, mods, q);
			if (mods == MOD_NONE)
				firstQuery = q;
			while (true)
			{
				switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
				{
					
					case Lucene.Net.QueryParsers.QueryParserConstants.AND: 
					case Lucene.Net.QueryParsers.QueryParserConstants.OR: 
					case Lucene.Net.QueryParsers.QueryParserConstants.NOT: 
					case Lucene.Net.QueryParsers.QueryParserConstants.PLUS: 
					case Lucene.Net.QueryParsers.QueryParserConstants.MINUS: 
					case Lucene.Net.QueryParsers.QueryParserConstants.LPAREN: 
					case Lucene.Net.QueryParsers.QueryParserConstants.QUOTED: 
					case Lucene.Net.QueryParsers.QueryParserConstants.TERM: 
					case Lucene.Net.QueryParsers.QueryParserConstants.PREFIXTERM: 
					case Lucene.Net.QueryParsers.QueryParserConstants.WILDTERM: 
					case Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_START: 
					case Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_START: 
					case Lucene.Net.QueryParsers.QueryParserConstants.NUMBER: 
						;
						break;
					
					default: 
						jj_la1[4] = jj_gen;
						goto label_1_brk;
					
				}
				conj = Conjunction();
				mods = Modifiers();
				q = Clause(field);
				AddClause(clauses, conj, mods, q);
			}

label_1_brk: ;
			
			if (clauses.Count == 1 && firstQuery != null)
			{
				if (true)
					return firstQuery;
			}
			else
			{
				{
					if (true)
						return GetBooleanQuery(clauses);
				}
			}
			throw new System.ApplicationException("Missing return statement in function");
		}
		
		public Query Clause(System.String field)
		{
			Query q;
			Token fieldToken = null, boost = null;
			if (Jj_2_1(2))
			{
				fieldToken = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.TERM);
				Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.COLON);
				field = DiscardEscapeChar(fieldToken.image);
			}
			else
			{
				;
			}
			switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
			{
				
				case Lucene.Net.QueryParsers.QueryParserConstants.QUOTED: 
				case Lucene.Net.QueryParsers.QueryParserConstants.TERM: 
				case Lucene.Net.QueryParsers.QueryParserConstants.PREFIXTERM: 
				case Lucene.Net.QueryParsers.QueryParserConstants.WILDTERM: 
				case Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_START: 
				case Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_START: 
				case Lucene.Net.QueryParsers.QueryParserConstants.NUMBER: 
					q = Term(field);
					break;
				
				case Lucene.Net.QueryParsers.QueryParserConstants.LPAREN: 
					Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.LPAREN);
					q = Query(field);
					Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RPAREN);
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.CARAT: 
							Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.CARAT);
							boost = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.NUMBER);
							break;
						
						default: 
							jj_la1[5] = jj_gen;
							;
							break;
						
					}
					break;
				
				default: 
					jj_la1[6] = jj_gen;
					Jj_consume_token(- 1);
					throw new ParseException();
				
			}
			if (boost != null)
			{
				float f = (float) 1.0;
				try
				{
					f = (float) System.Single.Parse(boost.image);
					q.SetBoost(f);
				}
				catch (System.Exception ignored)
				{
				}
			}
			{
				if (true)
					return q;
			}
			throw new System.ApplicationException("Missing return statement in function");
		}
		
		public Query Term(System.String field)
		{
			Token term, boost = null, fuzzySlop = null, goop1, goop2;
			bool prefix = false;
			bool wildcard = false;
			bool fuzzy = false;
			bool rangein = false;
			Query q;
			switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
			{
				
				case Lucene.Net.QueryParsers.QueryParserConstants.TERM: 
				case Lucene.Net.QueryParsers.QueryParserConstants.PREFIXTERM: 
				case Lucene.Net.QueryParsers.QueryParserConstants.WILDTERM: 
				case Lucene.Net.QueryParsers.QueryParserConstants.NUMBER: 
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.TERM: 
							term = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.TERM);
							break;
						
						case Lucene.Net.QueryParsers.QueryParserConstants.PREFIXTERM: 
							term = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.PREFIXTERM);
							prefix = true;
							break;
						
						case Lucene.Net.QueryParsers.QueryParserConstants.WILDTERM: 
							term = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.WILDTERM);
							wildcard = true;
							break;
						
						case Lucene.Net.QueryParsers.QueryParserConstants.NUMBER: 
							term = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.NUMBER);
							break;
						
						default: 
							jj_la1[7] = jj_gen;
							Jj_consume_token(- 1);
							throw new ParseException();
						
					}
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.FUZZY_SLOP: 
							fuzzySlop = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.FUZZY_SLOP);
							fuzzy = true;
							break;
						
						default: 
							jj_la1[8] = jj_gen;
							;
							break;
						
					}
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.CARAT: 
							Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.CARAT);
							boost = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.NUMBER);
							switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
							{
								
								case Lucene.Net.QueryParsers.QueryParserConstants.FUZZY_SLOP: 
									fuzzySlop = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.FUZZY_SLOP);
									fuzzy = true;
									break;
								
								default: 
									jj_la1[9] = jj_gen;
									;
									break;
								
							}
							break;
						
						default: 
							jj_la1[10] = jj_gen;
							;
							break;
						
					}
					System.String termImage = DiscardEscapeChar(term.image);
					if (wildcard)
					{
						q = GetWildcardQuery(field, termImage);
					}
					else if (prefix)
					{
						q = GetPrefixQuery(field, DiscardEscapeChar(term.image.Substring(0, (term.image.Length - 1) - (0))));
					}
					else if (fuzzy)
					{
						float fms = fuzzyMinSim;
						try
						{
							fms = (float) System.Single.Parse(fuzzySlop.image.Substring(1).Replace(".", 
								System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator));
						}
						catch (System.Exception ignored)
						{
						}
						if (fms < 0.0f || fms > 1.0f)
						{
							{
								if (true)
									throw new ParseException("Minimum similarity for a FuzzyQuery has to be between 0.0f and 1.0f !");
							}
						}
						q = GetFuzzyQuery(field, termImage, fms);
					}
					else
					{
						q = GetFieldQuery(field, termImage);
					}
					break;
				
				case Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_START: 
					Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_START);
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_GOOP: 
							goop1 = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_GOOP);
							break;
						
						case Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_QUOTED: 
							goop1 = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_QUOTED);
							break;
						
						default: 
							jj_la1[11] = jj_gen;
							Jj_consume_token(- 1);
							throw new ParseException();
						
					}
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_TO: 
							Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_TO);
							break;
						
						default: 
							jj_la1[12] = jj_gen;
							;
							break;
						
					}
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_GOOP: 
							goop2 = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_GOOP);
							break;
						
						case Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_QUOTED: 
							goop2 = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_QUOTED);
							break;
						
						default: 
							jj_la1[13] = jj_gen;
							Jj_consume_token(- 1);
							throw new ParseException();
						
					}
					Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_END);
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.CARAT: 
							Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.CARAT);
							boost = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.NUMBER);
							break;
						
						default: 
							jj_la1[14] = jj_gen;
							;
							break;
						
					}
					if (goop1.kind == Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_QUOTED)
					{
						goop1.image = goop1.image.Substring(1, (goop1.image.Length - 1) - (1));
					}
					else
					{
						goop1.image = DiscardEscapeChar(goop1.image);
					}
					if (goop2.kind == Lucene.Net.QueryParsers.QueryParserConstants.RANGEIN_QUOTED)
					{
						goop2.image = goop2.image.Substring(1, (goop2.image.Length - 1) - (1));
					}
					else
					{
						goop2.image = DiscardEscapeChar(goop2.image);
					}
					q = GetRangeQuery(field, goop1.image, goop2.image, true);
					break;
				
				case Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_START: 
					Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_START);
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_GOOP: 
							goop1 = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_GOOP);
							break;
						
						case Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_QUOTED: 
							goop1 = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_QUOTED);
							break;
						
						default: 
							jj_la1[15] = jj_gen;
							Jj_consume_token(- 1);
							throw new ParseException();
						
					}
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_TO: 
							Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_TO);
							break;
						
						default: 
							jj_la1[16] = jj_gen;
							;
							break;
						
					}
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_GOOP: 
							goop2 = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_GOOP);
							break;
						
						case Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_QUOTED: 
							goop2 = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_QUOTED);
							break;
						
						default: 
							jj_la1[17] = jj_gen;
							Jj_consume_token(- 1);
							throw new ParseException();
						
					}
					Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_END);
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.CARAT: 
							Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.CARAT);
							boost = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.NUMBER);
							break;
						
						default: 
							jj_la1[18] = jj_gen;
							;
							break;
						
					}
					if (goop1.kind == Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_QUOTED)
					{
						goop1.image = goop1.image.Substring(1, (goop1.image.Length - 1) - (1));
					}
					else
					{
						goop1.image = DiscardEscapeChar(goop1.image);
					}
					if (goop2.kind == Lucene.Net.QueryParsers.QueryParserConstants.RANGEEX_QUOTED)
					{
						goop2.image = goop2.image.Substring(1, (goop2.image.Length - 1) - (1));
					}
					else
					{
						goop2.image = DiscardEscapeChar(goop2.image);
					}
					
					q = GetRangeQuery(field, goop1.image, goop2.image, false);
					break;
				
				case Lucene.Net.QueryParsers.QueryParserConstants.QUOTED: 
					term = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.QUOTED);
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.FUZZY_SLOP: 
							fuzzySlop = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.FUZZY_SLOP);
							break;
						
						default: 
							jj_la1[19] = jj_gen;
							;
							break;
						
					}
					switch ((jj_ntk == - 1) ? Jj_ntk() : jj_ntk)
					{
						
						case Lucene.Net.QueryParsers.QueryParserConstants.CARAT: 
							Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.CARAT);
							boost = Jj_consume_token(Lucene.Net.QueryParsers.QueryParserConstants.NUMBER);
							break;
						
						default: 
							jj_la1[20] = jj_gen;
							;
							break;
						
					}
					int s = phraseSlop;
					
					if (fuzzySlop != null)
					{
						try
						{
							s = (int) System.Single.Parse(fuzzySlop.image.Substring(1));
						}
						catch (System.Exception ignored)
						{
						}
					}
					q = GetFieldQuery(field, term.image.Substring(1, (term.image.Length - 1) - (1)), s);
					break;
				
				default: 
					jj_la1[21] = jj_gen;
					Jj_consume_token(- 1);
					throw new ParseException();
				
			}
			if (boost != null)
			{
				float f = (float) 1.0;
				try
				{
					f = (float) System.Single.Parse(boost.image);
				}
				catch (System.Exception ignored)
				{
					/* Should this be handled somehow? (defaults to "no boost", if
					* boost number is invalid)
					*/
				}
				
				// avoid boosting null queries, such as those caused by stop words
				if (q != null)
				{
					q.SetBoost(f);
				}
			}
			{
				if (true)
					return q;
			}
			throw new System.ApplicationException("Missing return statement in function");
		}
		
		private bool Jj_2_1(int xla)
		{
			jj_la = xla; jj_lastpos = jj_scanpos = token;
			try
			{
				return !Jj_3_1();
			}
			catch (LookaheadSuccess ls)
			{
				return true;
			}
			finally
			{
				Jj_save(0, xla);
			}
		}
		
		private bool Jj_3_1()
		{
			if (Jj_scan_token(Lucene.Net.QueryParsers.QueryParserConstants.TERM))
				return true;
			if (Jj_scan_token(Lucene.Net.QueryParsers.QueryParserConstants.COLON))
				return true;
			return false;
		}
		
		public QueryParserTokenManager token_source;
		public Token token, jj_nt;
		private int jj_ntk;
		private Token jj_scanpos, jj_lastpos;
		private int jj_la;
		public bool lookingAhead = false;
		private bool jj_semLA;
		private int jj_gen;
		private int[] jj_la1 = new int[22];
		private static uint[] jj_la1_0;
		private static void  Jj_la1_0()
		{
			jj_la1_0 = new uint[]{0x180, 0x180, 0xe00, 0xe00, 0xfb1f80, 0x8000, 0xfb1000, 0x9a0000, 0x40000, 0x40000, 0x8000, 0xc000000, 0x1000000, 0xc000000, 0x8000, 0xc0000000, 0x10000000, 0xc0000000, 0x8000, 0x40000, 0x8000, 0xfb0000};
		}
		private JJCalls[] jj_2_rtns;
		private bool jj_rescan = false;
		private int jj_gc = 0;
		
		public QueryParser(CharStream stream)
		{
			InitBlock();
			token_source = new QueryParserTokenManager(stream);
			token = new Token();
			jj_ntk = - 1;
			jj_gen = 0;
			for (int i = 0; i < 22; i++)
				jj_la1[i] = - 1;
			for (int i = 0; i < jj_2_rtns.Length; i++)
				jj_2_rtns[i] = new JJCalls();
		}
		
		public virtual void  ReInit(CharStream stream)
		{
			token_source.ReInit(stream);
			token = new Token();
			jj_ntk = - 1;
			jj_gen = 0;
			for (int i = 0; i < 22; i++)
				jj_la1[i] = - 1;
			for (int i = 0; i < jj_2_rtns.Length; i++)
				jj_2_rtns[i] = new JJCalls();
		}
		
		public QueryParser(QueryParserTokenManager tm)
		{
			InitBlock();
			token_source = tm;
			token = new Token();
			jj_ntk = - 1;
			jj_gen = 0;
			for (int i = 0; i < 22; i++)
				jj_la1[i] = - 1;
			for (int i = 0; i < jj_2_rtns.Length; i++)
				jj_2_rtns[i] = new JJCalls();
		}
		
		public virtual void  ReInit(QueryParserTokenManager tm)
		{
			token_source = tm;
			token = new Token();
			jj_ntk = - 1;
			jj_gen = 0;
			for (int i = 0; i < 22; i++)
				jj_la1[i] = - 1;
			for (int i = 0; i < jj_2_rtns.Length; i++)
				jj_2_rtns[i] = new JJCalls();
		}
		
		private Token Jj_consume_token(int kind)
		{
			Token oldToken;
			if ((oldToken = token).next != null)
				token = token.next;
			else
				token = token.next = token_source.GetNextToken();
			jj_ntk = - 1;
			if (token.kind == kind)
			{
				jj_gen++;
				if (++jj_gc > 100)
				{
					jj_gc = 0;
					for (int i = 0; i < jj_2_rtns.Length; i++)
					{
						JJCalls c = jj_2_rtns[i];
						while (c != null)
						{
							if (c.gen < jj_gen)
								c.first = null;
							c = c.next;
						}
					}
				}
				return token;
			}
			token = oldToken;
			jj_kind = kind;
			throw GenerateParseException();
		}
		
		[Serializable]
		private sealed class LookaheadSuccess:System.ApplicationException
		{
		}
		private LookaheadSuccess jj_ls;
		private bool Jj_scan_token(int kind)
		{
			if (jj_scanpos == jj_lastpos)
			{
				jj_la--;
				if (jj_scanpos.next == null)
				{
					jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.GetNextToken();
				}
				else
				{
					jj_lastpos = jj_scanpos = jj_scanpos.next;
				}
			}
			else
			{
				jj_scanpos = jj_scanpos.next;
			}
			if (jj_rescan)
			{
				int i = 0; Token tok = token;
				while (tok != null && tok != jj_scanpos)
				{
					i++; tok = tok.next;
				}
				if (tok != null)
					Jj_add_error_token(kind, i);
			}
			if (jj_scanpos.kind != kind)
				return true;
			if (jj_la == 0 && jj_scanpos == jj_lastpos)
				throw jj_ls;
			return false;
		}
		
		public Token GetNextToken()
		{
			if (token.next != null)
				token = token.next;
			else
				token = token.next = token_source.GetNextToken();
			jj_ntk = - 1;
			jj_gen++;
			return token;
		}
		
		public Token GetToken(int index)
		{
			Token t = lookingAhead ? jj_scanpos : token;
			for (int i = 0; i < index; i++)
			{
				if (t.next != null)
					t = t.next;
				else
					t = t.next = token_source.GetNextToken();
			}
			return t;
		}
		
		private int Jj_ntk()
		{
			if ((jj_nt = token.next) == null)
				return (jj_ntk = (token.next = token_source.GetNextToken()).kind);
			else
				return (jj_ntk = jj_nt.kind);
		}
		
		private System.Collections.ArrayList jj_expentries = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
		private int[] jj_expentry;
		private int jj_kind = - 1;
		private int[] jj_lasttokens = new int[100];
		private int jj_endpos;
		
		private void  Jj_add_error_token(int kind, int pos)
		{
			if (pos >= 100)
				return ;
			if (pos == jj_endpos + 1)
			{
				jj_lasttokens[jj_endpos++] = kind;
			}
			else if (jj_endpos != 0)
			{
				jj_expentry = new int[jj_endpos];
				for (int i = 0; i < jj_endpos; i++)
				{
					jj_expentry[i] = jj_lasttokens[i];
				}
				bool exists = false;
				for (System.Collections.IEnumerator e = jj_expentries.GetEnumerator(); e.MoveNext(); )
				{
					int[] oldentry = (int[]) (e.Current);
					if (oldentry.Length == jj_expentry.Length)
					{
						exists = true;
						for (int i = 0; i < jj_expentry.Length; i++)
						{
							if (oldentry[i] != jj_expentry[i])
							{
								exists = false;
								break;
							}
						}
						if (exists)
							break;
					}
				}
				if (!exists)
					jj_expentries.Add(jj_expentry);
				if (pos != 0)
					jj_lasttokens[(jj_endpos = pos) - 1] = kind;
			}
		}
		
		public virtual ParseException GenerateParseException()
		{
			jj_expentries.Clear();
			bool[] la1tokens = new bool[32];
			for (int i = 0; i < 32; i++)
			{
				la1tokens[i] = false;
			}
			if (jj_kind >= 0)
			{
				la1tokens[jj_kind] = true;
				jj_kind = - 1;
			}
			for (int i = 0; i < 22; i++)
			{
				if (jj_la1[i] == jj_gen)
				{
					for (int j = 0; j < 32; j++)
					{
						if ((jj_la1_0[i] & (1 << j)) != 0)
						{
							la1tokens[j] = true;
						}
					}
				}
			}
			for (int i = 0; i < 32; i++)
			{
				if (la1tokens[i])
				{
					jj_expentry = new int[1];
					jj_expentry[0] = i;
					jj_expentries.Add(jj_expentry);
				}
			}
			jj_endpos = 0;
			Jj_rescan_token();
			Jj_add_error_token(0, 0);
			int[][] exptokseq = new int[jj_expentries.Count][];
			for (int i = 0; i < jj_expentries.Count; i++)
			{
				exptokseq[i] = (int[]) jj_expentries[i];
			}
			return new ParseException(token, exptokseq, Lucene.Net.QueryParsers.QueryParserConstants.tokenImage);
		}
		
		public void  Enable_tracing()
		{
		}
		
		public void  Disable_tracing()
		{
		}
		
		private void  Jj_rescan_token()
		{
			jj_rescan = true;
			for (int i = 0; i < 1; i++)
			{
				JJCalls p = jj_2_rtns[i];
				do 
				{
					if (p.gen > jj_gen)
					{
						jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
						switch (i)
						{
							
							case 0:  Jj_3_1(); break;
						}
					}
					p = p.next;
				}
				while (p != null);
			}
			jj_rescan = false;
		}
		
		private void  Jj_save(int index, int xla)
		{
			JJCalls p = jj_2_rtns[index];
			while (p.gen > jj_gen)
			{
				if (p.next == null)
				{
					p = p.next = new JJCalls(); break;
				}
				p = p.next;
			}
			p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
		}
		
		internal sealed class JJCalls
		{
			internal int gen;
			internal Token first;
			internal int arg;
			internal JJCalls next;
		}
		static QueryParser()
		{
			{
				Jj_la1_0();
			}
		}
	}
}